#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MCP 高级数学运算服务

本服务提供全面的数学运算功能，包括：
- 基础四则运算
- 高级数学函数（幂、根、三角函数、对数等）
- 统计计算
- 数值转换
- 实用工具
"""

from mcp.server.fastmcp import FastMCP
from typing import Union, List
import decimal
import math
import statistics
import re

# 创建 MCP 服务实例
mcp = FastMCP("Advanced Math Calculator Server")

# 设置decimal精度
decimal.getcontext().prec = 50

# 常用数学常数
PI = decimal.Decimal(str(math.pi))
E = decimal.Decimal(str(math.e))

# 辅助函数
def safe_decimal(value: Union[int, float, str]) -> decimal.Decimal:
    """安全转换为Decimal类型"""
    try:
        return decimal.Decimal(str(value))
    except (ValueError, decimal.InvalidOperation) as e:
        raise ValueError(f"无效的数值: {value}")

def format_result(result: decimal.Decimal, precision: int = 10) -> str:
    """格式化结果，移除不必要的尾随零"""
    # 四舍五入到指定精度
    rounded = result.quantize(decimal.Decimal('0.' + '0' * precision))
    # 转换为字符串并移除尾随零
    result_str = str(rounded).rstrip('0').rstrip('.')
    return result_str if result_str else '0'

# ============================================================================
# 数学计算工具
# ============================================================================

@mcp.tool()
def add(a: Union[int, float, str], b: Union[int, float, str]) -> str:
    """加法运算
    
    Args:
        a: 第一个数
        b: 第二个数
        
    Returns:
        两数之和
    """
    try:
        result = safe_decimal(a) + safe_decimal(b)
        return format_result(result)
    except Exception as e:
        raise ValueError(f"加法运算错误: {e}")

@mcp.tool()
def subtract(a: Union[int, float, str], b: Union[int, float, str]) -> str:
    """减法运算
    
    Args:
        a: 第一个数
        b: 第二个数
        
    Returns:
        两数之差
    """
    try:
        result = safe_decimal(a) - safe_decimal(b)
        return format_result(result)
    except Exception as e:
        raise ValueError(f"减法运算错误: {e}")

@mcp.tool()
def multiply(a: Union[int, float, str], b: Union[int, float, str]) -> str:
    """乘法运算
    
    Args:
        a: 第一个数
        b: 第二个数
        
    Returns:
        两数之积
    """
    try:
        result = safe_decimal(a) * safe_decimal(b)
        return format_result(result)
    except Exception as e:
        raise ValueError(f"乘法运算错误: {e}")

@mcp.tool()
def divide(a: Union[int, float, str], b: Union[int, float, str]) -> str:
    """除法运算
    
    Args:
        a: 被除数
        b: 除数
        
    Returns:
        两数之商
    """
    try:
        divisor = safe_decimal(b)
        if divisor == 0:
            raise ValueError("除数不能为零")
        result = safe_decimal(a) / divisor
        return format_result(result)
    except Exception as e:
        raise ValueError(f"除法运算错误: {e}")

# ============================================================================
# 高级数学函数
# ============================================================================

@mcp.tool()
def power(base: Union[int, float, str], exponent: Union[int, float, str]) -> str:
    """幂运算
    
    Args:
        base: 底数
        exponent: 指数
        
    Returns:
        base的exponent次幂
    """
    try:
        base_decimal = safe_decimal(base)
        exp_decimal = safe_decimal(exponent)
        
        # 使用math库进行幂运算，然后转换为Decimal
        result = decimal.Decimal(str(float(base_decimal) ** float(exp_decimal)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"幂运算错误: {e}")

@mcp.tool()
def square_root(number: Union[int, float, str]) -> str:
    """平方根
    
    Args:
        number: 被开方数
        
    Returns:
        number的平方根
    """
    try:
        num = safe_decimal(number)
        if num < 0:
            raise ValueError("负数不能开平方根")
        result = num.sqrt()
        return format_result(result)
    except Exception as e:
        raise ValueError(f"平方根运算错误: {e}")

@mcp.tool()
def nth_root(number: Union[int, float, str], n: Union[int, float, str]) -> str:
    """n次方根
    
    Args:
        number: 被开方数
        n: 根的次数
        
    Returns:
        number的n次方根
    """
    try:
        num = safe_decimal(number)
        root = safe_decimal(n)
        
        if root == 0:
            raise ValueError("根的次数不能为零")
        
        # 使用幂运算计算n次方根: x^(1/n)
        result = decimal.Decimal(str(float(num) ** (1 / float(root))))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"n次方根运算错误: {e}")

@mcp.tool()
def factorial(n: Union[int, str]) -> str:
    """阶乘运算
    
    Args:
        n: 非负整数
        
    Returns:
        n的阶乘
    """
    try:
        num = int(safe_decimal(n))
        if num < 0:
            raise ValueError("阶乘的参数必须是非负整数")
        if num > 1000:
            raise ValueError("数值过大，无法计算阶乘")
        
        result = decimal.Decimal(str(math.factorial(num)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"阶乘运算错误: {e}")

@mcp.tool()
def logarithm(number: Union[int, float, str], base: Union[int, float, str] = "e") -> str:
    """对数运算
    
    Args:
        number: 真数
        base: 底数，默认为e（自然对数）
        
    Returns:
        以base为底number的对数
    """
    try:
        num = safe_decimal(number)
        if num <= 0:
            raise ValueError("真数必须大于0")
        
        if base == "e":
            result = decimal.Decimal(str(math.log(float(num))))
        else:
            base_decimal = safe_decimal(base)
            if base_decimal <= 0 or base_decimal == 1:
                raise ValueError("底数必须大于0且不等于1")
            result = decimal.Decimal(str(math.log(float(num), float(base_decimal))))
        
        return format_result(result)
    except Exception as e:
        raise ValueError(f"对数运算错误: {e}")

@mcp.tool()
def sin(angle: Union[int, float, str], unit: str = "radians") -> str:
    """正弦函数
    
    Args:
        angle: 角度
        unit: 角度单位，"radians"（弧度）或"degrees"（度）
        
    Returns:
        角度的正弦值
    """
    try:
        angle_decimal = safe_decimal(angle)
        angle_float = float(angle_decimal)
        
        if unit == "degrees":
            angle_float = math.radians(angle_float)
        elif unit != "radians":
            raise ValueError("角度单位必须是'radians'或'degrees'")
        
        result = decimal.Decimal(str(math.sin(angle_float)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"正弦运算错误: {e}")

@mcp.tool()
def cos(angle: Union[int, float, str], unit: str = "radians") -> str:
    """余弦函数
    
    Args:
        angle: 角度
        unit: 角度单位，"radians"（弧度）或"degrees"（度）
        
    Returns:
        角度的余弦值
    """
    try:
        angle_decimal = safe_decimal(angle)
        angle_float = float(angle_decimal)
        
        if unit == "degrees":
            angle_float = math.radians(angle_float)
        elif unit != "radians":
            raise ValueError("角度单位必须是'radians'或'degrees'")
        
        result = decimal.Decimal(str(math.cos(angle_float)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"余弦运算错误: {e}")

@mcp.tool()
def tan(angle: Union[int, float, str], unit: str = "radians") -> str:
    """正切函数
    
    Args:
        angle: 角度
        unit: 角度单位，"radians"（弧度）或"degrees"（度）
        
    Returns:
        角度的正切值
    """
    try:
        angle_decimal = safe_decimal(angle)
        angle_float = float(angle_decimal)
        
        if unit == "degrees":
            angle_float = math.radians(angle_float)
        elif unit != "radians":
            raise ValueError("角度单位必须是'radians'或'degrees'")
        
        result = decimal.Decimal(str(math.tan(angle_float)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"正切运算错误: {e}")

# ============================================================================
# 统计计算函数
# ============================================================================

@mcp.tool()
def mean(numbers: str) -> str:
    """计算平均值
    
    Args:
        numbers: 用逗号分隔的数字字符串，如"1,2,3,4,5"
        
    Returns:
        数字列表的平均值
    """
    try:
        num_list = [float(safe_decimal(x.strip())) for x in numbers.split(',')]
        if not num_list:
            raise ValueError("数字列表不能为空")
        
        result = decimal.Decimal(str(statistics.mean(num_list)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"平均值计算错误: {e}")

@mcp.tool()
def median(numbers: str) -> str:
    """计算中位数
    
    Args:
        numbers: 用逗号分隔的数字字符串，如"1,2,3,4,5"
        
    Returns:
        数字列表的中位数
    """
    try:
        num_list = [float(safe_decimal(x.strip())) for x in numbers.split(',')]
        if not num_list:
            raise ValueError("数字列表不能为空")
        
        result = decimal.Decimal(str(statistics.median(num_list)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"中位数计算错误: {e}")

@mcp.tool()
def standard_deviation(numbers: str) -> str:
    """计算标准差
    
    Args:
        numbers: 用逗号分隔的数字字符串，如"1,2,3,4,5"
        
    Returns:
        数字列表的标准差
    """
    try:
        num_list = [float(safe_decimal(x.strip())) for x in numbers.split(',')]
        if len(num_list) < 2:
            raise ValueError("计算标准差至少需要两个数字")
        
        result = decimal.Decimal(str(statistics.stdev(num_list)))
        return format_result(result)
    except Exception as e:
        raise ValueError(f"标准差计算错误: {e}")

# ============================================================================
# 实用工具函数
# ============================================================================

@mcp.tool()
def percentage(part: Union[int, float, str], whole: Union[int, float, str]) -> str:
    """计算百分比
    
    Args:
        part: 部分值
        whole: 总值
        
    Returns:
        百分比（%）
    """
    try:
        part_decimal = safe_decimal(part)
        whole_decimal = safe_decimal(whole)
        
        if whole_decimal == 0:
            raise ValueError("总值不能为零")
        
        result = (part_decimal / whole_decimal) * 100
        return f"{format_result(result)}%"
    except Exception as e:
        raise ValueError(f"百分比计算错误: {e}")

@mcp.tool()
def absolute_value(number: Union[int, float, str]) -> str:
    """计算绝对值
    
    Args:
        number: 数字
        
    Returns:
        数字的绝对值
    """
    try:
        num = safe_decimal(number)
        result = abs(num)
        return format_result(result)
    except Exception as e:
        raise ValueError(f"绝对值计算错误: {e}")

@mcp.tool()
def round_number(number: Union[int, float, str], decimal_places: int = 0) -> str:
    """四舍五入
    
    Args:
        number: 要四舍五入的数字
        decimal_places: 保留的小数位数
        
    Returns:
        四舍五入后的数字
    """
    try:
        num = safe_decimal(number)
        if decimal_places < 0:
            raise ValueError("小数位数不能为负数")
        
        # 创建量化器
        quantizer = decimal.Decimal('0.' + '0' * decimal_places) if decimal_places > 0 else decimal.Decimal('1')
        result = num.quantize(quantizer, rounding=decimal.ROUND_HALF_UP)
        return format_result(result)
    except Exception as e:
        raise ValueError(f"四舍五入错误: {e}")

@mcp.tool()
def get_constants() -> str:
    """获取数学常数
    
    Returns:
        常用数学常数的值
    """
    return f"π (Pi) = {format_result(PI)}\ne = {format_result(E)}"

@mcp.tool()
def evaluate_expression(expression: str) -> str:
    """计算数学表达式
    
    Args:
        expression: 数学表达式字符串，支持基本运算符和函数
        
    Returns:
        表达式的计算结果
    """
    try:
        # 安全的表达式评估（仅支持基本数学运算）
        # 移除空格
        expr = expression.replace(' ', '')
        
        # 检查是否包含危险字符
        dangerous_chars = ['import', 'exec', 'eval', '__', 'open', 'file']
        if any(char in expr.lower() for char in dangerous_chars):
            raise ValueError("表达式包含不安全的内容")
        
        # 替换常数
        expr = expr.replace('pi', str(PI)).replace('e', str(E))
        
        # 使用eval计算（在受限环境中）
        allowed_names = {
            "__builtins__": {},
            "abs": abs,
            "pow": pow,
            "round": round,
            "min": min,
            "max": max,
        }
        
        result = eval(expr, allowed_names)
        return format_result(decimal.Decimal(str(result)))
    except Exception as e:
        raise ValueError(f"表达式计算错误: {e}")

# 启动服务
if __name__ == "__main__":
    mcp.run(transport="stdio")